module vgalab2(
//	Clock Input
  input CLOCK_50,	//	50 MHz
  input CLOCK_27,     //      27 MHz
//	Push Button
  input [3:0] KEY,      //	Pushbutton[3:0]
//	DPDT Switch
  input [17:0] SW,		//	Toggle Switch[17:0]
//	7-SEG Display
  output [6:0]	HEX0,HEX1,HEX2,HEX3,HEX4,HEX5,HEX6,HEX7,  // Seven Segment Digits
//	LED
  output [8:0]	LEDG,  //	LED Green[8:0]
  output [17:0] LEDR,  //	LED Red[17:0]
//	GPIO
 inout [35:0] GPIO_0,GPIO_1,	//	GPIO Connections
//	TV Decoder
//TD_DATA,    	//	TV Decoder Data bus 8 bits
//TD_HS,		//	TV Decoder H_SYNC
//TD_VS,		//	TV Decoder V_SYNC
  output TD_RESET,	//	TV Decoder Reset
// VGA
  output VGA_CLK,   						//	VGA Clock
  output VGA_HS,							//	VGA H_SYNC
  output VGA_VS,							//	VGA V_SYNC
  output VGA_BLANK,						//	VGA BLANK
  output VGA_SYNC,						//	VGA SYNC
  output [9:0] VGA_R,   						//	VGA Red[9:0]
  output [9:0] VGA_G,	 						//	VGA Green[9:0]
  output [9:0] VGA_B   						//	VGA Blue[9:0]
);

//	All inout port turn to tri-state
assign	GPIO_0		=	36'hzzzzzzzzz;
assign	GPIO_1		=	36'hzzzzzzzzz;

// reset delay gives some time for peripherals to initialize
wire DLY_RST;
Reset_Delay r0(	.iCLK(CLOCK_50),.oRESET(DLY_RST) );

wire [6:0] blank = 7'b111_1111;

// blank unused 7-segment digits
assign HEX0 = blank;
assign HEX1 = blank;
assign HEX2 = blank;
assign HEX3 = blank;
assign HEX4 = blank;
assign HEX5 = blank;
assign HEX6 = blank;
assign HEX7 = blank;

wire		VGA_CTRL_CLK;
wire		AUD_CTRL_CLK;
wire [9:0]	mVGA_R;
wire [9:0]	mVGA_G;
wire [9:0]	mVGA_B;
wire [9:0]	mCoord_X;
wire [9:0]	mCoord_Y;

assign	TD_RESET = 1'b1; // Enable 27 MHz

VGA_Audio_PLL 	p1 (	
	.areset(~DLY_RST),
	.inclk0(CLOCK_27),
	.c0(VGA_CTRL_CLK),
	.c1(AUD_CTRL_CLK),
	.c2(VGA_CLK)
);


textbox u3(
	.CLOCK_50(CLOCK_50),
	.SW(SW),
	.KEY(KEY),
	.LEDR(LEDR),
	.LEDG(LEDG),
	.iCLK1(VGA_CLK),
	.iCLK2(VGA_CTRL_CLK),
	.px(mCoord_X),
	.py(mCoord_Y),
	.valid(valid),
	.pixel(pixel)
);
wire valid, pixel;
wire s = valid & pixel;

parameter WHITE = 10'hFFF;
parameter BLACK = 10'h000;

/*
assign mVGA_R = (s? WHITE: BLACK);
assign mVGA_G = (s? WHITE: BLACK);
assign mVGA_B = (s? WHITE: BLACK);
*/
assign mVGA_R = (s? BLACK: WHITE);
assign mVGA_G = (s? BLACK: WHITE);
assign mVGA_B = (s? BLACK: WHITE);


vga_sync u1(
   .iCLK(VGA_CTRL_CLK),
   .iRST_N(DLY_RST),	
   .iRed(mVGA_R),
   .iGreen(mVGA_G),
   .iBlue(mVGA_B),
   // pixel coordinates
   .px(mCoord_X),
   .py(mCoord_Y),
   // VGA Side
   .VGA_R(VGA_R),
   .VGA_G(VGA_G),
   .VGA_B(VGA_B),
   .VGA_H_SYNC(VGA_HS),
   .VGA_V_SYNC(VGA_VS),
   .VGA_SYNC(VGA_SYNC),
   .VGA_BLANK(VGA_BLANK)
);


endmodule

module chars (
	address,
	clock,
	data,
	wren,
	q);

	input	[10:0]  address;
	input	  clock;
	input	[7:0]  data;
	input	  wren;
	output	[7:0]  q;
	

	wire [7:0] sub_wire0;
	wire [7:0] q = sub_wire0[7:0];
 
 
	altsyncram	altsyncram_component (
				.wren_a (wren),
				.clock0 (clock),
				.address_a (address),
				.data_a (data),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_b (1'b0));
	defparam
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_output_a = "BYPASS",
		altsyncram_component.init_file = "chars.mif",
		altsyncram_component.intended_device_family = "Cyclone II",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 2048,
		altsyncram_component.operation_mode = "SINGLE_PORT",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "UNREGISTERED",
		altsyncram_component.power_up_uninitialized = "FALSE",
		altsyncram_component.widthad_a = 11,
		altsyncram_component.width_a = 8,
		altsyncram_component.width_byteena_a = 1;


endmodule


module textbox(
	input CLOCK_50,
	input [17:0]SW,
	input [3:0]KEY,
	input iCLK1,iCLK2,
	input [9:0] px,
	input [9:0] py,
	output reg[7:0]LEDG,
	output reg[17:0]LEDR,
	output reg valid,
	output pixel
);
parameter COLS = 64;
parameter ROWS = 32;
wire rst = SW[17];
wire clk = !KEY[3]|!KEY[2]|!KEY[1];
reg [1:0]s;
reg [1:0]ns;
reg [3:0]countw=1'd0;
reg [3:0]countr=1'd0;


parameter	Q1	=	3'd0,
				Q2 =	3'd1,
				Q3	=	3'd2,
				Q4	=	3'd3,
				Q5 = 	3'd4;
			
			
				


always@(posedge clk or negedge rst)
begin
	if (!rst)
	begin
		s <= Q1;

	end
	else
		s <= s+1'b1;
end

// test that we are inside the textbox
always@(*)
begin
			
			
	case(s)

	Q1: begin
					if (px>=COLS*8) valid <= 1'b0;
					else if (py>=ROWS*4) valid <= 1'b0;
					else valid <= 1'b1;
					
					
			end
	Q2: begin
					if (px>=COLS*8) valid <= 1'b0;
					else if (py>=ROWS*7) valid <= 1'b0;
					else valid <= 1'b1;
					
					
			end
	Q3: begin
					if (px>=COLS*8) valid <= 1'b0;
					else if (py>=ROWS*10) valid <= 1'b0;
					else valid <= 1'b1;
					
					
			end
	Q4: begin
					if (px>=COLS*8) valid <= 1'b0;
					else if (py>=ROWS*16) valid <= 1'b0;
					else valid <= 1'b1;
					
							
			end
	Q5: begin
					if (px>=COLS*8) valid <= 1'b0;
					else if (py>=ROWS*16) valid <= 1'b0;
					else valid <= 1'b1;
					
							
			end
		endcase
end

always@(*)
begin
	case(s)
	Q1: //correct answer a
	begin
		if(!KEY[2])
		begin
			LEDG[0]=1'b1;			
			LEDR[0]=1'b0;
			
			countr=3'd0;
			countw=3'd0;
			countr=countr+1'd1;
		end
		else if(!KEY[1]|!KEY[3])
		begin
			LEDR[0]=1'b1;
			LEDG[0]=1'b0;
			
			countr=3'd0;
			countw=1'd1;
			countw=countw+1'd1;
		end
		else
		begin
			countr=3'd0;
			countw=3'd0;
			LEDR[13:0]=1'b0;
			LEDG[3:0]=1'b0;
		end
	end
	Q2: //correct answer b
	begin
		if(!KEY[2])
		begin
			LEDG[0]=1'b1;			
			LEDR[0]=1'b0;
			
			countr=countr+1'd1;
		end
		else if(!KEY[1]|!KEY[3])
		begin
			LEDR[0]=1'b1;
			LEDG[0]=1'b0;

			countw=countw+1'd1;
	
		end
		else
		begin
			LEDR[13:0]=1'b0;
			LEDG[3:0]=1'b0;
		end
	end
	Q3: //correct answer c
	begin
		if(!KEY[3])
		begin
			LEDG[0]=1'b1;
			LEDR[0]=1'b0;
			
			countr=countr+1'd1;
		end
		else if(!KEY[1]|!KEY[2])
		begin
			LEDR[0]=1'b1;
			LEDG[0]=1'b0;
			
			countw=countw+1'd1;
		end
		else
		begin
			LEDR[13:0]=1'b0;
			LEDG[3:0]=1'b0;
		end
	end
	Q4: //correct answer d
	begin
		if(!KEY[1])
		begin
			LEDG[0]=1'b1;			
			LEDR[0]=1'b0;
			
			countr=countr+1'd1;
		end
		else if(!KEY[2]|!KEY[3])
		begin
			LEDR[0]=1'b1;
			LEDG[0]=1'b0;
			
			countw=countw+1'd1;
		end
		else
		begin
			LEDR[13:0]=1'b0;
			LEDG[3:0]=1'b0;
		end
	end
	endcase
end


always@(*)
begin	
case(s)



		
Q2:begin if (countw==3'd1) begin LEDR[17:14]=4'b0001; end
else if (countr==3'd1) begin LEDG[7:4]=4'b0001; end
else  begin LEDG[7:4]=4'b0000;
		LEDR[17:14]=4'b0000; end end
		
Q3:begin if (countw==3'd2) begin LEDR[17:14]=4'b0011; end
else if (countr==3'd2) begin LEDG[7:4]=4'b0011; end end	

Q4:begin if (countw==3'd3) begin LEDR[17:14]=4'b0111; end
else if (countr==3'd3) begin LEDG[7:4]=4'b0111; end end	

Q5:begin if (countw==3'd4) begin LEDR[17:14]=4'b1111; end
else if (countr==3'd4) begin LEDG[7:4]=4'b1111; end end	


endcase
end


/*		if(SW[0]==1'b0 && SW[1]==1'b0 && SW[2]==1'b0)
			begin
				s<=2'd0;
			end
		if(SW[0]==1'b0 && SW[1]==1'b1 && SW[2]==1'b0)
			begin
				s<=2'd1;
			end
		if(SW[0]==1'b0 && SW[1]==1'b0 && SW[2]==1'b1)
			begin
				s<=2'd2;
			end
		if(SW[0]==1'b1 && SW[1]==1'b0 && SW[2]==1'b0)
			begin
				s<=2'd3;
			end

end
*/

// instantiate text memory

chars mem1(
	.address(character_address),
	.clock(~iCLK1),
	.wren(1'b0),
	.q(qchr)
	);

// calculate character address
wire [10:0] character_address = {py[8:4],px[8:3]};
wire [7:0] qchr;

// instantiate sysfont memory
sysfont mem2(
	.address(address),
	.clock(iCLK2),
	.q(q)
	);
wire [10:0] address = {	qchr[6:0], py[3:0] };
wire [7:0] q;
reg rom_mux_output;

	// Mux to pick off correct rom data bit from 8-bit word
	// for on screen character generation
	always
	case (px[2:0])
	0: rom_mux_output = q[0];
	1: rom_mux_output = q[7];
	2: rom_mux_output = q[6];
	3: rom_mux_output = q[5];
	4: rom_mux_output = q[4];
	5: rom_mux_output = q[3];
	6: rom_mux_output = q[2];
	7: rom_mux_output = q[1];
	endcase
	
	assign pixel = rom_mux_output;
	
endmodule

module sysfont (
	address,
	clock,
	q);

	input	[10:0]  address;
	input	  clock;
	output	[7:0]  q;

	wire [7:0] sub_wire0;
	wire [7:0] q = sub_wire0[7:0];

	altsyncram	altsyncram_component (
				.clock0 (clock),
				.address_a (address),
				.q_a (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.address_b (1'b1),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clock1 (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_a ({8{1'b1}}),
				.data_b (1'b1),
				.eccstatus (),
				.q_b (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_a (1'b0),
				.wren_b (1'b0));
	defparam
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_output_a = "BYPASS",
		altsyncram_component.init_file = "sysfont.mif",
		altsyncram_component.intended_device_family = "Cyclone II",
		altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 2048,
		altsyncram_component.operation_mode = "ROM",
		altsyncram_component.outdata_aclr_a = "NONE",
		altsyncram_component.outdata_reg_a = "UNREGISTERED",
		altsyncram_component.widthad_a = 11,
		altsyncram_component.width_a = 8,
		altsyncram_component.width_byteena_a = 1;


endmodule


module	Reset_Delay(iCLK,oRESET);
input		iCLK;
output reg	oRESET;
reg	[19:0]	Cont;

always@(posedge iCLK)
begin
	if(Cont!=20'hFFFFF)
	begin
		Cont	<=	Cont+1'b1;
		oRESET	<=	1'b0;
	end
	else
	oRESET	<=	1'b1;
end

endmodule


module VGA_Audio_PLL (
	areset,
	inclk0,
	c0,
	c1,
	c2);

	input	  areset;
	input	  inclk0;
	output	  c0;
	output	  c1;
	output	  c2;

	wire [5:0] sub_wire0;
	wire [0:0] sub_wire6 = 1'h0;
	wire [2:2] sub_wire3 = sub_wire0[2:2];
	wire [1:1] sub_wire2 = sub_wire0[1:1];
	wire [0:0] sub_wire1 = sub_wire0[0:0];
	wire  c0 = sub_wire1;
	wire  c1 = sub_wire2;
	wire  c2 = sub_wire3;
	wire  sub_wire4 = inclk0;
	wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};

	altpll	altpll_component (
				.inclk (sub_wire5),
				.areset (areset),
				.clk (sub_wire0),
				.activeclock (),
				.clkbad (),
				.clkena ({6{1'b1}}),
				.clkloss (),
				.clkswitch (1'b0),
				.configupdate (1'b0),
				.enable0 (),
				.enable1 (),
				.extclk (),
				.extclkena ({4{1'b1}}),
				.fbin (1'b1),
				.fbmimicbidir (),
				.fbout (),
				.locked (),
				.pfdena (1'b1),
				.phasecounterselect ({4{1'b1}}),
				.phasedone (),
				.phasestep (1'b1),
				.phaseupdown (1'b1),
				.pllena (1'b1),
				.scanaclr (1'b0),
				.scanclk (1'b0),
				.scanclkena (1'b1),
				.scandata (1'b0),
				.scandataout (),
				.scandone (),
				.scanread (1'b0),
				.scanwrite (1'b0),
				.sclkout0 (),
				.sclkout1 (),
				.vcooverrange (),
				.vcounderrange ());
	defparam
		altpll_component.clk0_divide_by = 15,
		altpll_component.clk0_duty_cycle = 50,
		altpll_component.clk0_multiply_by = 14,
		altpll_component.clk0_phase_shift = "0",
		altpll_component.clk1_divide_by = 3,
		altpll_component.clk1_duty_cycle = 50,
		altpll_component.clk1_multiply_by = 2,
		altpll_component.clk1_phase_shift = "0",
		altpll_component.clk2_divide_by = 15,
		altpll_component.clk2_duty_cycle = 50,
		altpll_component.clk2_multiply_by = 14,
		altpll_component.clk2_phase_shift = "-9921",
		altpll_component.compensate_clock = "CLK0",
		altpll_component.inclk0_input_frequency = 37037,
		altpll_component.intended_device_family = "Cyclone II",
		altpll_component.lpm_type = "altpll",
		altpll_component.operation_mode = "NORMAL",
		altpll_component.port_activeclock = "PORT_UNUSED",
		altpll_component.port_areset = "PORT_USED",
		altpll_component.port_clkbad0 = "PORT_UNUSED",
		altpll_component.port_clkbad1 = "PORT_UNUSED",
		altpll_component.port_clkloss = "PORT_UNUSED",
		altpll_component.port_clkswitch = "PORT_UNUSED",
		altpll_component.port_configupdate = "PORT_UNUSED",
		altpll_component.port_fbin = "PORT_UNUSED",
		altpll_component.port_inclk0 = "PORT_USED",
		altpll_component.port_inclk1 = "PORT_UNUSED",
		altpll_component.port_locked = "PORT_UNUSED",
		altpll_component.port_pfdena = "PORT_UNUSED",
		altpll_component.port_phasecounterselect = "PORT_UNUSED",
		altpll_component.port_phasedone = "PORT_UNUSED",
		altpll_component.port_phasestep = "PORT_UNUSED",
		altpll_component.port_phaseupdown = "PORT_UNUSED",
		altpll_component.port_pllena = "PORT_UNUSED",
		altpll_component.port_scanaclr = "PORT_UNUSED",
		altpll_component.port_scanclk = "PORT_UNUSED",
		altpll_component.port_scanclkena = "PORT_UNUSED",
		altpll_component.port_scandata = "PORT_UNUSED",
		altpll_component.port_scandataout = "PORT_UNUSED",
		altpll_component.port_scandone = "PORT_UNUSED",
		altpll_component.port_scanread = "PORT_UNUSED",
		altpll_component.port_scanwrite = "PORT_UNUSED",
		altpll_component.port_clk0 = "PORT_USED",
		altpll_component.port_clk1 = "PORT_USED",
		altpll_component.port_clk2 = "PORT_USED",
		altpll_component.port_clk3 = "PORT_UNUSED",
		altpll_component.port_clk4 = "PORT_UNUSED",
		altpll_component.port_clk5 = "PORT_UNUSED",
		altpll_component.port_clkena0 = "PORT_UNUSED",
		altpll_component.port_clkena1 = "PORT_UNUSED",
		altpll_component.port_clkena2 = "PORT_UNUSED",
		altpll_component.port_clkena3 = "PORT_UNUSED",
		altpll_component.port_clkena4 = "PORT_UNUSED",
		altpll_component.port_clkena5 = "PORT_UNUSED",
		altpll_component.port_extclk0 = "PORT_UNUSED",
		altpll_component.port_extclk1 = "PORT_UNUSED",
		altpll_component.port_extclk2 = "PORT_UNUSED",
		altpll_component.port_extclk3 = "PORT_UNUSED";


endmodule


module vga_sync(
   input iCLK, // 25 MHz clock
   input iRST_N,
   input [9:0] iRed,
   input [9:0] iGreen,
   input [9:0] iBlue,
   // pixel coordinates
   output [9:0] px,
   output [9:0] py,
   // VGA Side
   output  [9:0] VGA_R,
   output  [9:0] VGA_G,
   output  [9:0] VGA_B,
   output reg VGA_H_SYNC,
   output reg VGA_V_SYNC,
   output VGA_SYNC,
   output VGA_BLANK
);

assign	VGA_BLANK	=	VGA_H_SYNC & VGA_V_SYNC;
assign	VGA_SYNC	=	1'b0;

reg [9:0] h_count, v_count;
assign px = h_count;
assign py = v_count;


// Horizontal sync

/* Generate Horizontal and Vertical Timing Signals for Video Signal
* h_count counts pixels (640 + extra time for sync signals)
* 
*  horiz_sync  ------------------------------------__________--------
*  h_count       0                640             659       755    799
*/
parameter H_SYNC_TOTAL = 800;
parameter H_PIXELS =     640;
parameter H_SYNC_START = 659;
parameter H_SYNC_WIDTH =  96;

always@(posedge iCLK or negedge iRST_N)
begin
   if(!iRST_N)
   begin
      h_count <= 10'h000;
      VGA_H_SYNC <= 1'b0;
   end
   else
   begin
      // H_Sync Counter
      if (h_count < H_SYNC_TOTAL-1) h_count <= h_count + 1'b1;
      else h_count <= 10'h0000;

      if (h_count >= H_SYNC_START && 
	h_count < H_SYNC_START+H_SYNC_WIDTH) VGA_H_SYNC = 1'b0;
      else VGA_H_SYNC <= 1'b1;
   end
end
/*  
*  vertical_sync      -----------------------------------------------_______------------
*  v_count             0                                      480    493-494          524
*/
parameter V_SYNC_TOTAL = 557;//origionally 525
parameter V_PIXELS     = 480;
parameter V_SYNC_START = 493;
parameter V_SYNC_WIDTH =   2;
parameter H_START = 699;

always @(posedge iCLK or negedge iRST_N)
begin
   if (!iRST_N)
   begin
      v_count <= 10'h0000;
      VGA_V_SYNC <= 1'b0;
   end
   else if (h_count == H_START)
   begin
      // V_Sync Counter
      if (v_count < V_SYNC_TOTAL-1) v_count <= v_count + 1'b1;
      else v_count <= 10'h0000;

      if (v_count >= V_SYNC_START && 
		v_count < V_SYNC_START+V_SYNC_WIDTH) VGA_V_SYNC = 1'b0;
      else VGA_V_SYNC <= 1'b1;
   end
end
   
wire video_h_on = (h_count<H_PIXELS);
wire video_v_on = (v_count<V_PIXELS);
wire video_on = video_h_on & video_v_on;

assign VGA_R = (video_on? iRed: 10'h000);
assign VGA_G = (video_on? iGreen: 10'h000);
assign VGA_B = (video_on? iBlue: 10'h000);
   
endmodule
